package kgame5.enginex {
import kgame5.enginex.comp.IBlock;
import kgame5.enginex.comp.ICollideP2E;
import kgame5.enginex.comp.ICollideP2P;
import kgame5.enginex.comp.ILogic;
import kgame5.enginex.comp.IRender;
import kgame5.enginex.event.EntityMessageEvent;
import kgame5.k3d.pars.ParticlesEngine;
import kgame5.kgu.spacial.SpacialManager;

import flash.display.Sprite;
import flash.utils.Dictionary;

/**
 * @author kk
 * 游戏世界，
 * 在wrold.addGameObject的时候，当判断go是一个bar时，自动添加到MovementManager中。
 * 持有
统一由World来管理。world负责持有和操作，总控调度.内含worldViewComp
add
remove
update
find
 * 
 * 把kengine里的World和EngineContext拿来用
 */
public class GameWorldX implements ISenceWorld{
	
	private var spacialManager:SpacialManager;//地图碰撞管理器,负责人物移动相关
	
	private var worldRender:WorldRender;//3D世界的渲染器
	
	private var cameraEntityVO:CameraEntityVO;//摄像机vo.摄像机要单独处理
	
	private var bDebug:Boolean=true;
	
	//注意mc_c放到这里，就是为了防止忘记mc_c.addChild(gameWorld.getDO());
	public function GameWorldX(mc_c:Sprite,viewportWidth:int,viewportHeight:int,bDebug:Boolean=true){
		
		spacialManager=new SpacialManager();
		
		worldRender=new WorldRender(mc_c,viewportWidth,viewportHeight,bDebug);
		
		ParticlesEngine.getInstance().setRoot(worldRender);//设置粒子引擎的根节点
		
		this.bDebug=bDebug;//如果是debug则不使用摄像机自由移动，TODO摄像机机制需要整理
	}
	
	//处理消息
	private function dispatchEntityMessage(e:EntityMessageEvent):void{
		var mvo:EntityMessageVO = e.messageVO;
		switch(mvo.scope) {
			case EntityMessageVO.SCOPE_SOMEONE://发送到某人
				var ent:Entity=findEntity(mvo.toID);
				this.doSendMessage(ent, mvo);
			break;
			case EntityMessageVO.SCOPE_BY_CATEID://发送到大类，比如全体坦克，或全体炮弹
				for each(var ent:Entity in dict_byCateID[mvo.toID]){
					this.doSendMessage(ent, mvo);
				}
			break;
			case EntityMessageVO.SCOPE_BY_TYPEID://发送到某小类，比如直线飞行的炮弹
				for each(var ent:Entity in dict_byTypeID[mvo.toID]){
					this.doSendMessage(ent, mvo);
				}
			break;
			case EntityMessageVO.SCOPE_ALL://发送到全体
				for each(var ent:Entity in dict_all){
					this.doSendMessage(ent, mvo);
				}
			break;
		}
	}

	
	private function doSendMessage(ent:Entity,mvo:EntityMessageVO):void{
		var h:ILogic=ent as ILogic;
		if(h!=null){
			h.handleEntityMessage(mvo);
		}
	}
	//--
	
	//返回某个大类的列表。比如坦克类，炮弹类
	public function getEntityListByCateID(cateID:int):Dictionary{
		return dict_byCateID[cateID];
	}
	
	//返回某个特定类的列表.好像用处不大.!想不出用处的暂时不实现
	public function getEntityListByTypeID(typeID:int):Dictionary{
		return dict_byTypeID[typeID];
	}
	
	public function getEntityList():Dictionary{
		return dict_all;
	}
	
	public function getEntityByID(id:int):Entity{
		return dict_all[id] as Entity;
	}
	
	
	
	private var dict_all:Dictionary;//全体
	
	private var arr_collider:Vector.<ICollideP2P>;//可碰撞的,执行碰撞
	
	private var arr_logic : Vector.<ILogic>;//全体fsmBatch
	
	private var arr_render:Vector.<IRender>;//不需要这个，renderList完全由3D引擎去搞
	
	//--发送事件用的,也是SenceWorld的一部分--
	//根据cateID分类，元素是dict[entID]=Entity
	private var dict_byCateID:Dictionary;//dict[cateID]=dict[id]<Entity>
	//根据typeID分类的,元素是dict[entID]=Entity
	private var dict_byTypeID:Dictionary;//dict[typeID]=dict[id]<Entity>
	
	
	//CC,RC,CellSize如果是俯视视角的则使用这个，否则不使用
	public function init(CC:int,RC:int,CellSize:int):void{
		dict_all=new Dictionary();
		arr_collider=new Vector.<ICollideP2P>();
		arr_logic=new Vector.<ILogic>();
		arr_render=new Vector.<IRender>();
		
		dict_byCateID=new Dictionary();
		dict_byTypeID=new Dictionary();
		
		spacialManager.Init(CC, RC, CellSize, null);//
		
		worldRender.start();
	}
	
	public function clear():void{
		//--粒子系统的 清除.粒子系统是个独立系统，不需要在pureMvc体系内
		ParticlesEngine.getInstance().clear();
		
		worldRender.clear();
	}
	
	//!!3D引擎执行渲染，这个是在onEnterFrame里做的，而不是在onTick里
	//曾经一直放到onTick里，导致了dead spril,就是帧频越低，我还去补上丢失的帧，连3d渲染也在重新计算！！
	public function onFrame():void{
		
		//--粒子系统的运动.粒子系统无关紧要
		ParticlesEngine.getInstance().update();
		
		//--真实渲染
		this.worldRender.render();
	}
	
	//丢失的逻辑会在这里补充上的
	public function onTick():void{
		//检测碰撞，将结果填充到一个表中
		this.updateColliderList();
		
		//执行Logic更新
		this.updateLogicList();
		
		//摄像机更新
		if(bDebug==false){
			this.updateCamera();//由cameraEntity的逻辑控制摄像机
		}
		
		//执行渲染
		this.updateRenderList();
	}
	
	
	
	
	//填充各个元素的碰撞列表
	private function updateColliderList():void{
		//T.p("---------------检测全体碰撞-----------");
		
		//先清除各个碰撞
		for each(var c:ICollideP2P in arr_collider){
			c.clearCollideList();//清除
		}
		
		var len:int=arr_collider.length;
		
		for(var i:int=0;i<len-1;i++){
			var src:ICollideP2P=arr_collider[i] as ICollideP2P;
			for(var j:int=i+1;j<len;j++){
				var aim:ICollideP2P=arr_collider[j] as ICollideP2P;
				
				if(src.getCollideHardVO().HitTestAABB(aim.getCollideHardVO())){
					src.addCollideItem((aim as Entity)._vo);
					aim.addCollideItem((src as Entity)._vo);
				}
			}
		}
	}
	
	//更新各个fsm
	private function updateLogicList():void{
		for each(var l:ILogic in arr_logic){
			l.updateLogic();
		}
	}
	
	//更新摄像机
	private function updateCamera():void{
		worldRender.camera.target.copy(cameraEntityVO.target);
		worldRender.camera.y=cameraEntityVO.y;
		worldRender.camera.pan=cameraEntityVO.pan;
		worldRender.camera.radius=cameraEntityVO.radius;
	}

	//执行渲染列表
	private function updateRenderList():void{
		for each(var r:IRender in arr_render){
			r.updateView();
		}
	}
	
	//===================增加删除之类的==================
	public function addEntity(ent:Entity):void{
		//T.p(this,"addEntity",ent._vo.id);
		if(dict_all[ent._vo.id]!=null){
			throw new Error("此id已被使用！"+ent._vo.id);
		}
		//-总类表中添加
		dict_all[ent._vo.id]=ent;
		
		//-判断是否是摄像机.注意只允许有一个摄像机
		if(ent is CameraEntity){
			this.cameraEntityVO=ent._vo as CameraEntityVO;
			
			//Temp,临时设置摄像机焦点~
			this.updateCamera();
		}
		
		//-地面障碍物
		if(ent is IBlock){
			//T.p("添加障碍物");
			spacialManager.AddBar((ent as IBlock).getBlockHardVO());
		}
		
		//-物体与物体碰撞
		if(ent is ICollideP2P) {
			arr_collider.push(ent);
		}
		
		//-逻辑
		if(ent is ILogic) {
			
			(ent as ILogic).setSenceWorld(this);//设定能被感知的世界
			
			arr_logic.push(ent);
			
			//注意，sendCommandEvent是被GamePlay感知并使用的
			//ent.addEventListener(SendCommandEvent.TYPE, listener)
			
			//发送消息
			ent.addEventListener(EntityMessageEvent.TYPE,dispatchEntityMessage);
		}
		
		//-可与地面碰撞
		if(ent is ICollideP2E){
			(ent as ICollideP2E).setSpacialManager(spacialManager);
		}
		
		//-可渲染
		if(ent is IRender) {
			//T.p("添加渲染对象");
			arr_render.push(ent);
			
			var r:IRender=ent as IRender;
			
			worldRender.addChild(r.getNode3D(),r.getNode3D().layerID);
			
			if(r.getShadow3D()!=null){//如果有影子则添加影子
				worldRender.addChild(r.getShadow3D(),r.getShadow3D().layerID);
			}
		}
		
		//-数据读取
		var cateID:int=ent._vo.cateID;
		var dict_cate:Dictionary=dict_byCateID[cateID];//按类分
		if(dict_cate==null){
			dict_cate=new Dictionary();
			dict_byCateID[cateID] = dict_cate;
		}
		dict_cate[ent._vo.id]=ent;
		
		//-
		var typeID:int=ent._vo.typeID;
		var dict_type:Dictionary=dict_byTypeID[typeID];//按类分
		if(dict_type==null){
			dict_type=new Dictionary();
			dict_byTypeID[typeID]=dict_type;
		}
		dict_type[ent._vo.id]=ent;
	}
	
	public function findEntity(id:int):Entity{
		return dict_all[id];
	}
	
	//返回是否删除成功
	public function removeEntity(id:int):void{
		
		var ent:Entity=findEntity(id);
		if(ent==null){
			return ;
		}
		
		//总列表中删除
		delete dict_all[id];
		
		//-地面障碍物
		if(ent is IBlock){
			spacialManager.RemoveBar((ent as IBlock).getBlockHardVO());
		}
		
		var idx:int;//临时用
		
		//-物体与物体碰撞
		if(ent is ICollideP2P) {
			var idx:int=arr_collider.indexOf(ent);
			if(idx!=-1){
				arr_collider.splice(idx, 1);
			}
			//Util.VectorRemoveElement(arr_collider, ent);//无法强制转换类型Vecor<XX>到Vector
		}
		
		//-状态机
		if(ent is ILogic) {
			var idx:int=arr_logic.indexOf(ent);
			if(idx!=-1){
				arr_logic.splice(idx, 1);
			}
			//Util.VectorRemoveElement(arr_logic, ent);
		}
		
		//-可渲染
		if(ent is IRender) {
			var idx:int=arr_render.indexOf(ent);
			if(idx!=-1){
				arr_render.splice(idx, 1);
			}
			//Util.VectorRemoveElement(arr_render, ent);
			var r:IRender=ent as IRender;
			worldRender.removeChild(r.getNode3D());
			
			if(r.getShadow3D()!=null){//如果有影子则删除影子
				worldRender.removeChild(r.getShadow3D());
			}
		}
		
		//-数据读取
		var dict_cate:Dictionary=dict_byCateID[ent._vo.cateID];//按类分
		if(dict_cate!=null){
			delete dict_cate[ent._vo.id];
		}
		
		//
		var dict_type:Dictionary=dict_byTypeID[ent._vo.typeID];//按类分
		if(dict_type!=null){
			delete dict_type[ent._vo.id];
		}
	}
}//end of class
}
